import java.util.*;

// 文件信息结构体（FileInfo）
class FileInfo {
    String fileName;               // 文件名字
    int fileSize;                  // 文件大小
    List<Integer> allocatedSectors; // 文件分配的扇区

    // 构造函数
    public FileInfo(String name, int size) {
        this.fileName = name;
        this.fileSize = size;
        this.allocatedSectors = new ArrayList<>(); // 初始化已分配扇区列表
    }
}

// 存储管理器结构体（StorageManager）
class StorageManager {
    int availableSectors;                       // 可用扇区总数
    int[][] bitmap;                             // 磁盘位图（二维数组）
    Map<String, FileInfo> files;                // 文件映射（键为文件名，值为文件信息）

    // 构造函数
    public StorageManager() {
        this.availableSectors = 128; // 初始化可用扇区数量
        this.bitmap = new int[8][16]; // 创建8柱面，每柱面16扇区的位图
        for (int j = 0; j < 16; j++) {
            bitmap[0][j] = 1; // 预留第一行作为系统文件，标记为已使用
        }
        files = new HashMap<>(); // 初始化文件映射
    }

    // 创建文件
    public boolean createFile(String name, int size) {
        // 检查文件是否已存在
        if (files.containsKey(name)) {
            System.out.println("错误: 文件已存在。");
            return false;
        }
        // 检查可用空间是否足够
        if (size > availableSectors) {
            System.out.println("错误: 空间不足。");
            return false;
        }

        // 创建新的文件信息
        FileInfo newFile = new FileInfo(name, size);
        // 更新位图和已分配扇区
        for (int i = 0; i < bitmap.length && size > 0; i++) {
            for (int j = 0; j < bitmap[i].length && size > 0; j++) {
                if (bitmap[i][j] == 0) { // 如果这个盘块为空
                    bitmap[i][j] = 1; // 设置为已分配
                    newFile.allocatedSectors.add(i * 16 + j); // 将扇区添加到已分配列表
                    size--; // 空闲区大小减少
                    availableSectors--; // 可用扇区数量减少
                }
            }
        }
        files.put(name, newFile); // 将文件信息存入映射
        fileDetails(newFile); // 显示文件详情
        return true; // 返回成功
    }

    // 显示存储状态
    public void displayStatus() {
        System.out.println("磁盘位图：");
        for (int[] row : bitmap) {
            for (int sector : row) {
                System.out.print(sector + " "); // 打印位图状态
            }
            System.out.println(); // 换行
        }

        System.out.println("\n文件列表:");
        for (FileInfo file : files.values()) {
            System.out.println(file.fileName + "\t大小: " + file.fileSize); // 显示文件名和大小
        }
        System.out.println();
    }

    // 显示文件详细信息
    public void fileDetails(FileInfo file) {
        System.out.println("文件 '" + file.fileName + "' 的详细信息：");
        for (int sector : file.allocatedSectors) {
            System.out.print("扇区: " + sector + "；"); // 遍历并显示分配的扇区
        }
        System.out.println();
    }

    // 删除文件
    public boolean deleteFile(String name) {
        // 检查文件是否存在
        if (!files.containsKey(name)) {
            System.out.println("错误: 文件不存在。");
            return false;
        }

        // 获取文件信息并释放分配的扇区
        FileInfo file = files.get(name);
        for (int sector : file.allocatedSectors) {
            int i = sector / 16; // 计算柱面
            int j = sector % 16; // 计算扇区
            bitmap[i][j] = 0; // 将位图标记为可用
            availableSectors++; // 增加可用扇区数量
        }
        files.remove(name); // 从映射中移除文件
        System.out.println("文件 '" + name + "' 已删除。");
        return true; // 返回成功
    }

    // SSTF 调度算法
    public void sstf(int currentPosition, List<Integer> requests) {
        boolean[] visited = new boolean[requests.size()]; // 记录请求的扇区是否被访问过
        List<Integer> order = new ArrayList<>(); // 存储调度顺序
        int totalRequests = requests.size();

        // 循环直到所有请求都被处理
        while (order.size() < totalRequests) {
            int minDistance = Integer.MAX_VALUE; // 初始化最小距离
            int nextIndex = -1; // 下一个处理的请求索引
            for (int i = 0; i < requests.size(); i++) {
                if (!visited[i]) { // 如果请求未被访问
                    int distance = Math.abs(currentPosition - requests.get(i)); // 计算距离
                    if (distance < minDistance) { // 找到最小距离
                        minDistance = distance;
                        nextIndex = i; // 记录下标
                    }
                }
            }
            if (nextIndex != -1) {
                visited[nextIndex] = true; // 标记请求为已访问
                order.add(requests.get(nextIndex)); // 添加到调度顺序
                currentPosition = requests.get(nextIndex); // 更新当前头部位置
            }
        }

        System.out.println("SSTF 调度顺序: " + order); // 输出调度顺序
    }

    // SCAN 调度算法
    public void scan(int currentPosition, List<Integer> requests, boolean direction) {
        requests.sort(Integer::compareTo); // 对请求进行排序
        List<Integer> order = new ArrayList<>(); // 存储调度顺序
        int position = currentPosition; // 当前头部位置

        if (direction) { // 向外移动
            for (int request : requests) {
                if (request >= position) {
                    order.add(request); // 添加大于或等于当前头部位置的请求
                }
            }
            for (int i = requests.size() - 1; i >= 0; i--) {
                if (requests.get(i) < position) {
                    order.add(requests.get(i)); // 添加小于当前头部位置的请求
                }
            }
        } else { // 向内移动
            for (int i = requests.size() - 1; i >= 0; i--) {
                if (requests.get(i) <= position) {
                    order.add(requests.get(i)); // 添加小于或等于当前头部位置的请求
                }
            }
            for (int request : requests) {
                if (request > position) {
                    order.add(request); // 添加大于当前头部位置的请求
                }
            }
        }

        System.out.println("SCAN 调度顺序: " + order); // 输出调度顺序
    }

    // CSCAN 调度算法
    public void cscan(int currentPosition, List<Integer> requests, boolean direction) {
        requests.sort(Integer::compareTo); // 对请求进行排序
        List<Integer> order = new ArrayList<>(); // 存储调度顺序
        int position = currentPosition; // 当前头部位置

        if (direction) { // 向外移动
            for (int request : requests) {
                if (request >= position) {
                    order.add(request); // 添加大于或等于当前头部位置的请求
                }
            }
            order.add(0); // 返回起始点（扇区0）
            for (int request : requests) {
                if (request < position) {
                    order.add(request); // 添加小于当前头部位置的请求
                }
            }
        } else { // 向内移动
            for (int i = requests.size() - 1; i >= 0; i--) {
                if (requests.get(i) <= position) {
                    order.add(requests.get(i)); // 添加小于或等于当前头部位置的请求
                }
            }
            order.add(127); // 返回终点（扇区127）
            for (int i = requests.size() - 1; i >= 0; i--) {
                if (requests.get(i) > position) {
                    order.add(requests.get(i)); // 添加大于当前头部位置的请求
                }
            }
        }

        System.out.println("CSCAN 调度顺序: " + order); // 输出调度顺序
    }
}

/**
 * @author spring
 */ // 主程序类
public class DiskScheduler {
    public static void main(String[] args) {
        StorageManager manager = new StorageManager(); // 创建存储管理器实例
        Scanner scanner = new Scanner(System.in); // 创建扫描器以获取用户输入
        int action; // 操作选择
        String filename; // 文件名
        int filesize; // 文件大小

        // 主循环，直到用户选择退出
        while (true) {
            System.out.println();
            manager.displayStatus(); // 显示当前存储状态
            System.out.println("根据数字提示选择操作: ");
            System.out.println("1: 创建文件, 2: 删除文件, 3: 调度算法, 4: 退出系统");
            action = scanner.nextInt(); // 获取用户操作

            switch (action) {
                case 1: // 创建文件
                    System.out.print("输入文件名: ");
                    filename = scanner.next();
                    System.out.print("输入文件大小: ");
                    filesize = scanner.nextInt();
                    if (manager.createFile(filename, filesize)) {
                        System.out.println("文件创建成功。");
                    }
                    break;
                case 2: // 删除文件
                    System.out.print("输入要删除的文件名: ");
                    filename = scanner.next();
                    if (manager.deleteFile(filename)) {
                        System.out.println("文件删除成功。");
                    }
                    break;
                case 3: // 调度算法选择
                    System.out.print("输入当前头部位置: ");
                    int currentPosition = scanner.nextInt();
                    List<Integer> requests = new ArrayList<>(); // 存储请求的扇区
                    System.out.println("输入请求的扇区（输入 -1 结束）:");
                    while (true) {
                        int request = scanner.nextInt();
                        if (request == -1) {
                            break; // 输入 -1 结束
                        }
                        requests.add(request); // 添加请求
                    }

                    System.out.print("选择调度算法 (1: SSTF, 2: SCAN, 3: CSCAN): ");
                    int algorithm = scanner.nextInt(); // 获取调度算法选择
                    switch (algorithm) {
                        case 1: // SSTF
                            manager.sstf(currentPosition, requests);
                            break;
                        case 2: // SCAN
                            System.out.print("选择方向 (1: 向外, 0: 向内): ");
                            boolean scanDirection = scanner.nextInt() == 1;
                            manager.scan(currentPosition, requests, scanDirection);
                            break;
                        case 3: // CSCAN
                            System.out.print("选择方向 (1: 向外, 0: 向内): ");
                            boolean cscanDirection = scanner.nextInt() == 1;
                            manager.cscan(currentPosition, requests, cscanDirection);
                            break;
                        default:
                            System.out.println("无效的操作。");
                    }
                    break;
                case 4: // 退出系统
                    System.out.println("程序退出。");
                    scanner.close(); // 关闭扫描器
                    return; // 退出主程序
                default: // 无效操作
                    System.out.println("无效的操作。");
            }
        }
    }
}
